package service

import (
	"context"
	"errors"
	"fmt"
	"order_srv/basic/config"
	__ "order_srv/basic/orderproto"
	"order_srv/handler/dao"
	"order_srv/handler/models"
	utils "order_srv/untils"
	"time"
)

// GenerateBilling 生成账单
func (s *Server) GenerateBilling(ctx context.Context, req *__.GenerateBillingReq) (*__.GenerateBillingResp, error) {
	var billing *models.Billing
	var err error

	switch req.BillType {
	case 1: // 日账单
		billing, err = dao.GenerateDailyBilling(req.UserId, uint8(req.UserType), req.Period)
	case 2: // 周账单
		// 解析年份和周数
		year, week := dao.ParseWeekPeriod(req.Period)
		billing, err = dao.GenerateWeeklyBilling(req.UserId, uint8(req.UserType), year, week)
	case 3: // 月账单
		// 解析年份和月份
		year, month := dao.ParseMonthPeriod(req.Period)
		billing, err = dao.GenerateMonthlyBilling(req.UserId, uint8(req.UserType), year, month)
	default:
		return nil, fmt.Errorf("不支持的账单类型: %d", req.BillType)
	}

	if err != nil {
		return nil, err
	}

	return &__.GenerateBillingResp{
		BillingId:    billing.ID,
		BillSn:       billing.BillSn,
		TotalIncome:  float32(billing.TotalIncome),
		TotalExpense: float32(billing.TotalExpense),
		NetAmount:    float32(billing.NetAmount),
		Status:       uint32(billing.Status),
		GeneratedAt:  billing.GeneratedAt.Format("2006-01-02 15:04:05"),
		Remark:       billing.Remark,
	}, nil
}

// GetBillingList 获取账单列表
func (s *Server) GetBillingList(ctx context.Context, req *__.GetBillingListReq) (*__.GetBillingListResp, error) {
	billings, total, err := dao.GetBillingByUser(req.UserId, uint8(req.UserType), int(req.Page), int(req.PageSize))
	if err != nil {
		return nil, err
	}

	var billingInfos []*__.BillingInfo
	for _, billing := range billings {
		billingInfo := &__.BillingInfo{
			Id:           billing.ID,
			BillSn:       billing.BillSn,
			BillType:     uint32(billing.BillType),
			BillPeriod:   billing.BillPeriod,
			TotalIncome:  float32(billing.TotalIncome),
			TotalExpense: float32(billing.TotalExpense),
			NetAmount:    float32(billing.NetAmount),
			Status:       uint32(billing.Status),
			GeneratedAt:  billing.GeneratedAt.Format("2006-01-02 15:04:05"),
			Remark:       billing.Remark,
		}

		if !billing.ConfirmedAt.IsZero() {
			billingInfo.ConfirmedAt = billing.ConfirmedAt.Format("2006-01-02 15:04:05")
		}

		billingInfos = append(billingInfos, billingInfo)
	}

	return &__.GetBillingListResp{
		Billings: billingInfos,
		Total:    int32(total),
		Page:     req.Page,
		PageSize: req.PageSize,
	}, nil
}

// GetBillingDetails 获取账单明细
func (s *Server) GetBillingDetails(ctx context.Context, req *__.GetBillingDetailsReq) (*__.GetBillingDetailsResp, error) {
	// 获取账单信息
	var billing models.Billing
	err := billing.GetByID(req.BillingId)
	if err != nil {
		return nil, err
	}

	// 获取账单明细
	details, err := dao.GetBillingDetails(req.BillingId)
	if err != nil {
		return nil, err
	}

	var detailInfos []*__.BillingDetailInfo
	for _, detail := range details {
		detailInfo := &__.BillingDetailInfo{
			Id:              detail.ID,
			OrderId:         detail.OrderID,
			OrderSn:         detail.OrderSn,
			ItemType:        uint32(detail.ItemType),
			ItemName:        detail.ItemName,
			Amount:          float32(detail.Amount),
			Description:     detail.Description,
			TransactionTime: detail.TransactionTime.Format("2006-01-02 15:04:05"),
		}
		detailInfos = append(detailInfos, detailInfo)
	}

	return &__.GetBillingDetailsResp{
		BillingId:    billing.ID,
		BillSn:       billing.BillSn,
		BillPeriod:   billing.BillPeriod,
		TotalIncome:  float32(billing.TotalIncome),
		TotalExpense: float32(billing.TotalExpense),
		NetAmount:    float32(billing.NetAmount),
		Status:       uint32(billing.Status),
		Details:      detailInfos,
	}, nil
}

// ConfirmBilling 确认账单
func (s *Server) ConfirmBilling(ctx context.Context, req *__.ConfirmBillingReq) (*__.ConfirmBillingResp, error) {
	err := dao.ConfirmBilling(req.BillingId)
	if err != nil {
		return nil, err
	}
	return &__.ConfirmBillingResp{
		Success: false,
		Message: "确认账单成功",
	}, nil
}

// DetectAbnormalTransactions 检测异常交易
func (s *Server) DetectAbnormalTransactions(ctx context.Context, req *__.DetectAbnormalTransactionsReq) (*__.DetectAbnormalTransactionsResp, error) {
	err := dao.DetectAbnormalTransactions()
	if err != nil {
		return nil, err
	}
	return &__.DetectAbnormalTransactionsResp{
		Success: true,
		Message: "检测异常交易成功",
	}, nil
}

// GetAbnormalTransactions 获取异常交易列表
func (s *Server) GetAbnormalTransactions(ctx context.Context, req *__.GetAbnormalTransactionsReq) (*__.GetAbnormalTransactionsResp, error) {
	transactions, total, err := dao.GetAbnormalTransactions(uint8(req.Status), int(req.Page), int(req.PageSize))
	if err != nil {
		return nil, err
	}

	var transactionInfos []*__.AbnormalTransactionInfo
	for _, transaction := range transactions {
		transactionInfo := &__.AbnormalTransactionInfo{
			Id:             transaction.ID,
			OrderId:        transaction.OrderID,
			OrderSn:        transaction.OrderSn,
			UserId:         transaction.UserID,
			AbnormalType:   uint32(transaction.AbnormalType),
			AbnormalDesc:   transaction.AbnormalDesc,
			ExpectedAmount: float32(transaction.ExpectedAmount),
			ActualAmount:   float32(transaction.ActualAmount),
			Status:         uint32(transaction.Status),
			ProcessResult:  transaction.ProcessResult,
			ProcessedBy:    transaction.ProcessedBy,
			CreateAt:       transaction.CreateAt.Format("2006-01-02 15:04:05"),
		}

		if !transaction.ProcessedAt.IsZero() {
			transactionInfo.ProcessedAt = transaction.ProcessedAt.Format("2006-01-02 15:04:05")
		}

		transactionInfos = append(transactionInfos, transactionInfo)
	}

	return &__.GetAbnormalTransactionsResp{
		Transactions: transactionInfos,
		Total:        int32(total),
		Page:         req.Page,
		PageSize:     req.PageSize,
	}, nil
}

// ProcessAbnormalTransaction 处理异常交易
func (s *Server) ProcessAbnormalTransaction(ctx context.Context, req *__.ProcessAbnormalTransactionReq) (*__.ProcessAbnormalTransactionResp, error) {
	err := dao.ProcessAbnormalTransaction(req.AbnormalId, req.ProcessResult, req.ProcessedBy)
	if err != nil {
		return nil, err
	}
	return &__.ProcessAbnormalTransactionResp{
		Success: true,
		Message: "处理异常交易成功",
	}, nil
}

// CreateDispute 创建争议
func (s *Server) CreateDispute(ctx context.Context, req *__.CreateDisputeReq) (*__.CreateDisputeResp, error) {
	dispute, err := dao.CreateDispute(req.BillingId, req.UserId, uint8(req.DisputeType), req.DisputeDesc, req.Evidence)
	if err != nil {
		return nil, err
	}

	return &__.CreateDisputeResp{
		DisputeId:   dispute.ID,
		BillingId:   dispute.BillingID,
		UserId:      dispute.UserID,
		DisputeType: uint32(dispute.DisputeType),
		DisputeDesc: dispute.DisputeDesc,
		Evidence:    dispute.Evidence,
		Status:      uint32(dispute.Status),
		CreateAt:    dispute.CreateAt.Format("2006-01-02 15:04:05"),
	}, nil
}

// ResolveDispute 解决争议
func (s *Server) ResolveDispute(ctx context.Context, req *__.ResolveDisputeReq) (*__.ResolveDisputeResp, error) {
	err := dao.ResolveDispute(req.DisputeId, req.Resolution, req.ResolvedBy)
	if err != nil {
		return nil, errors.New("处理争议失败")
	}
	return &__.ResolveDisputeResp{
		Success: true,
		Message: "处理争议成功",
	}, nil
}

// GetDisputeRecords 获取争议记录
func (s *Server) GetDisputeRecords(ctx context.Context, req *__.GetDisputeRecordsReq) (*__.GetDisputeRecordsResp, error) {
	disputes, total, err := dao.GetDisputeRecords(uint8(req.Status), int(req.Page), int(req.PageSize))
	if err != nil {
		return nil, err
	}

	var disputeInfos []*__.DisputeRecordInfo
	for _, dispute := range disputes {
		disputeInfo := &__.DisputeRecordInfo{
			Id:          dispute.ID,
			BillingId:   dispute.BillingID,
			UserId:      dispute.UserID,
			DisputeType: uint32(dispute.DisputeType),
			DisputeDesc: dispute.DisputeDesc,
			Evidence:    dispute.Evidence,
			Status:      uint32(dispute.Status),
			Resolution:  dispute.Resolution,
			ResolvedBy:  dispute.ResolvedBy,
			CreateAt:    dispute.CreateAt.Format("2006-01-02 15:04:05"),
		}

		if !dispute.ResolvedAt.IsZero() {
			disputeInfo.ResolvedAt = dispute.ResolvedAt.Format("2006-01-02 15:04:05")
		}

		disputeInfos = append(disputeInfos, disputeInfo)
	}

	return &__.GetDisputeRecordsResp{
		Disputes: disputeInfos,
		Total:    int32(total),
		Page:     req.Page,
		PageSize: req.PageSize,
	}, nil
}

// approveDispute 批准争议
func (s *Server) ApproveDispute(req *__.DisputeResolutionReq) (string, error) {
	// 批准争议，执行相应的补偿措施
	return fmt.Sprintf("批准争议，执行补偿：%s", req.Resolution), nil
}

// rejectDispute 拒绝争议
func (s *Server) RejectDispute(req *__.DisputeResolutionReq) (string, error) {
	// 拒绝争议
	return fmt.Sprintf("拒绝争议：%s", req.Resolution), nil
}

// compromiseDispute 妥协争议
func (s *Server) CompromiseDispute(req *__.DisputeResolutionReq) (string, error) {
	// 妥协解决争议
	return fmt.Sprintf("妥协解决争议：%s", req.Resolution), nil
}

// DisputeResolution 争议解决
func (s *Server) DisputeResolution(ctx context.Context, req *__.DisputeResolutionReq) (*__.DisputeResolutionResp, error) {
	// 参数验证
	if req.DisputeId == 0 {
		return nil, errors.New("争议ID不能为空")
	}

	if len(req.Resolution) == 0 {
		return nil, errors.New("解决方案不能为空")
	}

	if req.ResolvedBy == 0 {
		return nil, errors.New("解决人ID不能为空")
	}

	if len(req.Action) == 0 {
		return nil, errors.New("解决动作不能为空")
	}

	// 使用超时控制
	timeout := 30 * time.Second
	ctx, cancel := context.WithTimeout(ctx, timeout)
	defer cancel()

	// 使用重试机制检查争议是否存在
	var dispute models.DisputeRecord
	err := utils.RetryWithBackoff(ctx, utils.DefaultRetryConfig, func() error {
		return config.DB.Where("id = ?", req.DisputeId).First(&dispute).Error
	})
	if err != nil {
		return nil, fmt.Errorf("争议记录不存在: %v", err)
	}

	// 检查争议状态
	if dispute.Status == 3 { // 已解决
		return nil, errors.New("争议已解决，无法重复处理")
	}

	if dispute.Status == 4 { // 已关闭
		return nil, errors.New("争议已关闭，无法处理")
	}

	// 根据解决动作执行相应操作
	var result string
	var success bool

	switch req.Action {
	case "approve":
		result, err = s.ApproveDispute(req)
		success = (err == nil)
	case "reject":
		result, err = s.RejectDispute(req)
		success = (err == nil)
	case "compromise":
		result, err = s.CompromiseDispute(req)
		success = (err == nil)
	default:
		return nil, fmt.Errorf("不支持的解决动作: %s", req.Action)
	}

	if err != nil {
		return &__.DisputeResolutionResp{
			Success: false,
			Message: fmt.Sprintf("处理失败: %v", err),
		}, nil
	}

	// 使用事务更新争议状态和账单状态
	err = utils.WithTimeout(ctx, 10*time.Second, func(ctx context.Context) error {
		tx := config.DB.Begin()
		if tx.Error != nil {
			return tx.Error
		}
		defer func() {
			if r := recover(); r != nil {
				tx.Rollback()
			}
		}()

		// 更新争议状态
		updates := map[string]interface{}{
			"status":      3, // 已解决
			"resolution":  req.Resolution,
			"resolved_at": time.Now(),
			"resolved_by": req.ResolvedBy,
		}

		if err := tx.Model(&models.DisputeRecord{}).Where("id = ?", req.DisputeId).Updates(updates).Error; err != nil {
			tx.Rollback()
			return err
		}

		// 更新账单状态
		if err := tx.Model(&models.Billing{}).Where("id = ?", dispute.BillingID).Update("status", 2).Error; err != nil {
			tx.Rollback()
			return err
		}

		return tx.Commit().Error
	})

	if err != nil {
		return &__.DisputeResolutionResp{
			Success: false,
			Message: fmt.Sprintf("更新状态失败: %v", err),
		}, nil
	}

	// 异步记录解决日志
	go dao.LogDisputeResolution(req.DisputeId, req.ResolvedBy, req.Resolution)

	return &__.DisputeResolutionResp{
		Success:    success,
		Message:    result,
		ResolvedAt: time.Now().Format("2006-01-02 15:04:05"),
	}, nil
}

// CreateDisputeWithWorkflow 创建争议并启动工作流
func (s *Server) CreateDisputeWithWorkflow(ctx context.Context, req *__.CreateDisputeReq) (*__.CreateDisputeResp, error) {
	// 创建争议
	resp, err := s.CreateDispute(ctx, req)
	if err != nil {
		return nil, err
	}

	// 启动工作流
	workflow, err := dao.WorkflowManager.CreateDisputeWorkflow(resp.DisputeId, req.Priorty)
	if err != nil {
		// 如果工作流创建失败，记录错误但不影响争议创建
		fmt.Printf("创建工作流失败: %v\n", err)
	} else {
		fmt.Printf("争议工作流已启动: %s\n", workflow.ID)
	}

	return resp, nil
}
